package com.gzz.orchid.context.application.rbac.impl;

import com.gzz.orchid.common.core.authorization.UserContextHolder;
import com.gzz.orchid.common.core.model.ActionCmd;
import com.gzz.orchid.common.core.util.I18nUtil;
import com.gzz.orchid.context.application.rbac.IUserExecutor;
import com.gzz.orchid.context.application.rbac.command.ChangePasswordCmd;
import com.gzz.orchid.context.application.rbac.command.UserGrantCmd;
import com.gzz.orchid.context.application.rbac.command.UserSaveCmd;
import com.gzz.orchid.context.application.rbac.convert.UserConverter;
import com.gzz.orchid.context.domain.rbac.IRoleService;
import com.gzz.orchid.context.domain.rbac.IUserRepository;
import com.gzz.orchid.context.domain.rbac.IUserService;
import com.gzz.orchid.context.domain.rbac.entity.UserDo;
import com.gzz.orchid.context.domain.rbac.entity.UserId;
import com.gzz.orchid.context.infrastructure.definition.Action;
import com.gzz.orchid.context.infrastructure.definition.Status;
import com.gzz.orchid.context.infrastructure.persistence.entity.sys.SysPrivilegePo;
import com.gzz.orchid.context.infrastructure.persistence.entity.sys.SysUserPo;
import com.gzz.orchid.context.infrastructure.persistence.mapper.sys.SysPrivilegeMapper;
import com.gzz.orchid.context.infrastructure.persistence.mapper.sys.SysUserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;


/**
 * @author higmd
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserExecutor implements IUserExecutor {
    private final IUserRepository repository;
    private final SysUserMapper mapper;
    private final IUserService service;
    private final IRoleService roleService;
    private final SysPrivilegeMapper authorizeMapper;

    @Override
    public void save(UserSaveCmd saveCmd) {
        SysUserPo userPo;
        if (Objects.isNull(saveCmd.getId())) {
            userPo = new SysUserPo();
            userPo.setStatus(0);
        } else {
            userPo = mapper.getById(saveCmd.getId());
        }
        // 检查code的唯一性
        UserDo userDo = new UserDo();
        userDo.setUserName(saveCmd.getUserName());
        userDo.setId(userPo.getId());
        service.checkCodeUnique(userDo);
        //
        roleService.checkCodeExists(saveCmd.getRoleCode());
        //
        UserConverter
                .INSTANCE
                .updatePo(userPo, saveCmd);
        // 提供持久化
        if(Objects.isNull(userPo.getId())) {
            userPo.setPasswd("25678756");
            userPo.setSalt("887333");
            mapper.insert(userPo);
        }else{
            mapper.updateById(userPo);
        }
    }

    @Override
    public void delete(ActionCmd cmd) {
        List<UserDo> users = repository.findListByIds(cmd.getIds());
        // 验证 不符合抛出异常
        users.forEach(mDo -> {
            if (mDo.getStatus().equals(Status.ENABLED)) {
                throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]状态为[ %s]，不能删除"
                        , mDo.getUserName()
                        , I18nUtil.message(mDo.getStatus().getLabel())));
            }
        });
        //
        int num = 2;
        //mapper.deleteBatchByIds(Arrays.asList(cmd.getIds()));
        if (num != cmd.getIds().length) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("批量删除用户失败，请稍后再试"));
        }
    }

    @Override
    public void disable(ActionCmd cmd) {
        List<UserDo> users = repository.findListByIds(cmd.getIds());
        // 验证 不符合抛出异常
        users.forEach(mDo -> {
            if (!mDo.getStatus().equals(Status.ENABLED)) {
                throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]状态为[ %s]，不能禁用"
                        , mDo.getUserName()
                        , I18nUtil.message(mDo.getStatus().getLabel())));
            }
        });
        // 更新状态
        int num = repository.batchChangeStatus(Status.DISABLED, users);
        if (num != cmd.getIds().length) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("批量禁用用户失败，请稍后再试"));
        }
    }

    @Override
    public void enable(ActionCmd cmd) {
        List<UserDo> users = repository.findListByIds(cmd.getIds());
        // 验证 不符合抛出异常
        users.forEach(mDo -> {
            if (!mDo.getStatus().equals(Status.DISABLED)) {
                throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]状态为[ %s]，不能启用"
                        , mDo.getUserName()
                        , I18nUtil.message(mDo.getStatus().getLabel())));
            }
        });
        // 更新状态
        int num = repository.batchChangeStatus(Status.ENABLED, users);
        if (num != cmd.getIds().length) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("批量启用用户失败，请稍后再试"));
        }
    }

    @Override
    public void audit(ActionCmd cmd) {
        List<UserDo> users = repository.findListByIds(cmd.getIds());
        // 验证 不符合抛出异常
        users.forEach(mDo -> {
            if (!mDo.getStatus().equals(Status.CREATED)) {
                throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]状态为[ %s]，不能审核"
                        , mDo.getUserName()
                        , I18nUtil.message(mDo.getStatus().getLabel())));
            }
        });
        // 更新状态
        int num = repository.batchChangeStatus(Status.ENABLED, users);
        if (num != cmd.getIds().length) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("批量审核用户失败，请稍后再试"));
        }
    }

    @Override
    public void changePassword(ChangePasswordCmd cmd) {
        UserDo userDo = repository.findByCode(UserContextHolder.getUserCode());
        if (Objects.isNull(userDo)) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]不存在", cmd.getUserName()));
        }
        userDo.changePassword(cmd.getNewPasswd(), cmd.getOldPasswd());
        repository.changePassword(userDo);
    }

    @Override
    public void resetPassword(UserId code) {
        UserDo userDo = repository.findByCode(code.getValue());
        if (Objects.isNull(userDo)) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]不存在", UserContextHolder.getUserCode()));
        }
        userDo.resetPassword();
        repository.changePassword(userDo);
    }

    @Override
    public void grantPrivilege(UserGrantCmd cmd) {
        UserDo userDo = repository.findByCode(cmd.getUserCode());
        if (Objects.isNull(userDo)) {
            throw new IllegalArgumentException(I18nUtil.ofMessage("用户[%s]不存在", cmd.getUserCode()));
        }
        //
        List<SysPrivilegePo> authorizeList = cmd.getAuthorize().stream().map(m -> {
            SysPrivilegePo po = new SysPrivilegePo();
            po.setUserId(userDo.getId());
            po.setModuleCode(m.getModuleCode());
            po.setPurview(m.getActions().stream().mapToInt(Action::getValue).sum());
            po.setEffAt(cmd.getExpiryDate().getBegin());
            po.setExpAt(cmd.getExpiryDate().getEnd());
            return po;
        }).toList();
//        authorizeMapper.deleteByCondition(QueryCondition.create(SYS_PRIVILEGE_PO.USER_ID, "=", userDo.getId()));
//        authorizeMapper.insertBatchSelective(authorizeList);
    }
}
